#ifndef IGRAPH_H_
#define IGRAPH_H_

#include <memory.h>

#include <boost/shared_ptr.hpp>

#include "graph_support/GraphSupport.h"

#include "graph_support/utils/RTTIStorage.h"


namespace GRAPH_SUPPORT_NS
{

class IGraph
{
public:
	virtual ~IGraph()
	{
	}

public:
	/**
	 * label interface for edge attributes access / modifications
	 */
	typedef utils::IRTTIStorageLabel IEdgeAttributes;
	typedef boost::shared_ptr< IEdgeAttributes > IEdgeAttributesPtr;
	/**
	 * defined types:
	 * IAttributes - interface which provides pointer to attributes, see ::get() method
	 * Attributes - implementation which stores pointer, but doesn't own it
	 * 				is useful for provideing access for existing edges
	 * CpAttributes - implementation which copies structure T and gives pointer to copied one
	 * 				is useful for adding edges
	 * see TestIterateEdges, TestRTTIStorageTemplate, TestRTTICopyStorageTemplate for more details
	 */
	template< typename T >
	class EdgeAttributesImpl
	{
	public:
		typedef utils::IRTTIStorage< T > IAttributes;
		typedef utils::RTTIStorage< T > Attributes;
		typedef utils::RTTICpStorage< T > CpAttributes;
	};

	class IEdgeIterator
	{
	public:
		virtual ~IEdgeIterator() {};
	public:
		virtual bool notFinished() = 0;
		virtual void next() = 0;
		virtual size_t getDestination() = 0;
		virtual IEdgeAttributesPtr getEdgeAttributes() = 0;
	};
	typedef std::auto_ptr< IEdgeIterator > IEdgeIteratorPtr;

public:
	virtual size_t igetVertexCount() const = 0;
	/**
	 * for igetOutEdgesIterator() returns any iterator
	 * this usecase is needed for igetOutEdgesIterator( size_t vid, IEdgeIterator & iter )
	 * see document for next method and TestIteratorInteface for details
	 */
	virtual IEdgeIteratorPtr igetOutEdgesIterator( size_t vid = 0 ) = 0;
	/**
	 * same as previous method, just re-initializes iter to begin-iter.
	 * requires iter to have proper virtual type (type of iterator returned bu previous method is proper).
	 * throws exception if iter has wrong type.
	 * since this method doesn't allocate new object, it has better performance.
	 * example / usecase:
	 * IEdgeIteratorPtr iterPtr = igr.igetOutEdgesIterator( 0 );
	 * for ( ... iterPtr->next() ... ) // loop A
	 * igr.igetOutEdgesIterator( 0, * iterPtr );
	 * for ( ... iterPtr->next() ... ) // loop B
	 */
	virtual void igetOutEdgesIterator( size_t vid, IEdgeIterator & iter ) = 0;
	virtual void iaddEdge( size_t begVid, size_t endVid, const IEdgeAttributesPtr & iattrs ) = 0;
};

}

#endif /* IGRAPH_H_ */
